// some intergration use this hook so need to use relative path resolve
import validVer from '../utils/validVer';
import type { Advancement } from '../types/advancement'
import copyFolder from '../utils/node/copyFolder';
import { AstroError } from 'astro/errors';
import fs from "fs/promises";

type CombinedIdAdvancement = Advancement & {
  id: string
}

let highestVer: string;

const verList: string[] = [];

function judgeHighestVer(ver1: string, ver2: string) {
  const ver1Arr = ver1.split(".").slice(0, 3)
  const ver2Arr = ver2.split(".").slice(0, 3)

  for (let i = 0; i < 3; i++) {
    if (ver1Arr[i] > ver2Arr[i]) return ver1
    else if (ver1Arr[i] < ver2Arr[i]) return ver2
  }

  return ver1
}

await Promise.all(
  (await fs.readdir("extract/")).map(async file => {
    // file name like 1.1.4.jar
    const verNumArr = file.split(".").slice(0, 3)
    if (verNumArr.length !== 3) return
    const verName = verNumArr.join(".")
    if (await fs.lstat(`extract/${verName}/advancements`)) {
      verList.push(verName)
      if (!highestVer) highestVer = verName
      else if (judgeHighestVer(verName, highestVer) === verName) {
        highestVer = file.replace(".jar", "")
      }
    }
  })
)

/**
 * {
 *  "providencraft": {
 *    "1.1.4": {
 *      "id": "providencraft:main/providencraft",
 *    }
 *  }
 * }
 */
const advancementMap = new Map<string, Record<string, CombinedIdAdvancement>>()

async function fillAdvancementMap(basePath: string, ver: string, map: typeof advancementMap) {
  await Promise.all((await fs.readdir(basePath)).map(async folder => {
    const dirPath = `${basePath}/${folder}`
    const stat = await fs.lstat(dirPath)
    if ((stat.isDirectory())) {
      await Promise.all(
        (await fs.readdir(`${basePath}/${folder}`))
          .map(
            async file => {
              if (file.endsWith(".json")) {
                const filename = file.replace(".json", "")
                const res = JSON.parse(
                  await fs.readFile(`${basePath}/${folder}/${file}`, "utf-8")
                )
                const newObj = map.get(filename)
                if (newObj) {
                  newObj[ver] = {
                    ...res,
                    id: `providencraft:${folder}/${filename}`
                  }
                  map.set(filename, newObj)
                }
                else {
                  map.set(filename, {
                    [ver]: {
                      ...res,
                      id: `providencraft:${folder}/${filename}`
                    }
                  })
                }
              }
            }
          )
      )
    }
  }))
}

let cacheVerList: string[] = [];
try {
  // todo! remove invalid version
  cacheVerList = (await fs.readdir("./.cache/extract/temp")).filter(ver => !verList.includes(ver)).filter(validVer)
  // copy exists cache advancement to extract
  await Promise.all(cacheVerList.map(async ver => {
    await copyFolder(`./.cache/extract/temp/${ver}/data/providencraft/advancements`, `./extract/${ver}/advancements`)
  }))
} catch (e) {
  console.log("读取成就缓存出错！" + e);
}

// read cache from extract
for (const ver of verList) {
  await fillAdvancementMap(`extract/${ver}/advancements`, ver, advancementMap)
}

export { advancementMap }

export default function useAdvancement(filename: string, ver = highestVer) {
  const res = advancementMap.get(filename)
  if (!res) throw new AstroError("找不到指定的成就: " + filename)
  if (!res[ver]) throw new AstroError(`找不到指定版本 ${ver} 的成就: ` + filename)
  return res[ver]
}
